package com.caird.pmp.iot.message.impl;

import com.caird.pmp.iot.message.MessageBase;
import com.caird.pmp.iot.message.MessageUtils;
import io.netty.buffer.ByteBuf;
import lombok.Data;

import java.util.Date;

@Data
public class DeviceMessage0200 extends MessageBase {

    //ALARM BIT 常量
    public static final int ALARM_BIT_GNSS_ERROR = (1 << 4);    //GNSS模块异常
    public static final int ALARM_BIT_GNSS_AT_OPEN = (1 << 5);  //GNSS天线开路
    public static final int ALARM_BIT_GNSS_AT_SHORT = (1 << 6); //GNSS天线短路
    public static final int ALARM_BIT_POWER_LOW = (1 << 7);     //主电源欠压
    public static final int ALARM_BIT_POWER_OFF = (1 << 8);     //主电源掉电

    //STATUS BIT 常量
    public static final int STATUS_BIT_ACC = (1 << 0);
    public static final int STATUS_BIT_LOCATED = (1 << 1);
    public static final int STATUS_BIT_SOUTH = (1 << 2);
    public static final int STATUS_BIT_WEST = (1 << 3);
    public static final int STATIS_BIT_OIL_OFF = (1 << 10);


    public DeviceMessage0200() {
        setId((short)0x0200);
    }

    @Override
    public boolean decodeBody(ByteBuf raw) {

        byte[] bs = new byte[6];

        //报警标识
        alarm = raw.readInt();

        //状态标识
        status = raw.readInt();

        //纬度
        latitude = 1.0f * raw.readInt() / 1000000;
        if (getStatusBit(DeviceMessage0200.STATUS_BIT_SOUTH))
            latitude *= -1;

        //经度
        longitude = 1.0f * raw.readInt() / 1000000;
        if (getStatusBit(DeviceMessage0200.STATUS_BIT_WEST))
            longitude *= -1;

        //海拔（米）
        altitude = raw.readUnsignedShort();

        //速度(km/h)
        gpsSpeed = 1.0f * raw.readUnsignedShort() / 10;

        //航向（0-359,正北为0，顺时针）
        heading = raw.readShort();

        //时间
        raw.readBytes(bs);
        date = MessageUtils.decodeDate(bs);

        //附加信息项
        while (raw.readableBytes() > 2) {
            int id = raw.readUnsignedByte();
            int length = raw.readUnsignedByte();
            if (raw.readableBytes() < length)
                break;
            decodeAdditionalData(id, length, raw);
        }

        return true;
    }

    /**
     * 附加信息项解码
     */
    private void decodeAdditionalData(int id, int length, ByteBuf raw) {
        int index = raw.readerIndex();
        switch (id) {
            case 0x01:  //里程
                if (4 == length) {
                    mileage = 1.0f * raw.readUnsignedInt() / 10;
                }
                break;
            case 0x02:  //油量
                if (2 == length) {
                    oil = 1.0f * raw.readUnsignedShort() / 10;
                }
                break;
            case 0x30:  //网络信号
                if (1 == length) {
                    netSignal = raw.readByte();
                }
                break;
            case 0x31:  //定位卫星数
                if (1 == length) {
                    gnssSatelliteNum = raw.readByte();
                }
                break;
            default:
                break;
        }
        raw.readerIndex(index);
        raw.skipBytes(length);
    }

    @Override
    public boolean encodeBody(ByteBuf raw) {
        if (raw.writableBytes() < 32)
            return false;

        //报警标识
        raw.writeInt(alarm);

        //状态
        raw.writeInt(status);

        //纬度
        if (latitude < 0)
            latitude *= -1;
        raw.writeInt((int)(latitude * 1000000));

        //经度
        if (longitude < 0)
            longitude *= -1;
        raw.writeInt((int)(longitude * 1000000));

        //海拔
        raw.writeShort(altitude);

        //速度
        raw.writeShort((short)(gpsSpeed * 10));

        //方向
        raw.writeShort(heading);

        //时间戳
        raw.writeBytes(MessageUtils.encodeDate(date));

        return true;
    }


    public boolean getStatusBit(int bit) {
        return (status & bit) > 0;
    }

    public void setStatusBit(int bit, boolean bSet) {
        status = status & ~bit;
        if (bSet)
            status |= bit;
    }

    public boolean getAlarmBit(int bit) {
        return (alarm & bit) > 0;
    }

    public void setAlarmBit(int bit, boolean bSet) {
        alarm = alarm & ~bit;
        if (bSet)
            alarm |= bit;
    }

    //报警标识
    private int alarm;

    //状态标识
    private int status;

    //经度：正为东经
    private float longitude;

    //纬度：正为北纬
    private float latitude;

    //海拔：m
    private int altitude;

    //速度：km/h
    private float gpsSpeed;

    //航向：正北为0，顺时针
    private short heading;

    //时间戳
    private Date date;

    //# 附加信息 #

    //仪表里程：0.1km
    private Float mileage;

    //仪表油量：0.1L
    private Float oil;

    //网络信号
    private Byte netSignal;

    //定位卫星数
    private Byte gnssSatelliteNum;
}
